package cn.itcast.nems.journal.service.impl;

import cn.itcast.ic.common.bean.Page;
import cn.itcast.nems.base.api.ClazzApi;
import cn.itcast.nems.base.dto.ClazzDTO;
import cn.itcast.nems.common.enumeration.BizNumberTypeEnum;
import cn.itcast.nems.common.service.BizNumberService;
import cn.itcast.nems.journal.converter.JournalChangeDateConverter;
import cn.itcast.nems.journal.dto.JournalChangeDateDTO;
import cn.itcast.nems.journal.dto.JournalChangeDateLineCreate;
import cn.itcast.nems.journal.dto.JournalChangeDateSearch;
import cn.itcast.nems.journal.dto.JournalClazzStartDateChangedDTO;
import cn.itcast.nems.journal.service.JournalChangeDateLineService;
import cn.itcast.nems.journal.service.JournalChangeDateService;
import cn.itcast.nems.studentrecord.dao.condition.JournalChangeDateQuery;
import cn.itcast.nems.studentrecord.dao.dataobject.JournalChangeDateDO;
import cn.itcast.nems.studentrecord.dao.entity.JournalChangeDate;
import cn.itcast.nems.studentrecord.dao.mapper.JournalChangeDateMapper;
import cn.itcast.nems.studentrecord.dto.ClazzStudentResultDTO;
import cn.itcast.nems.studentrecord.dto.StudentRecordStudentDTO;
import cn.itcast.nems.studentrecord.dto.change.StudentRecordJournalInDateChangeDTO;
import cn.itcast.nems.studentrecord.service.StudentRecordClazzStartDateChangedService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 改期凭单-头 服务实现类
 * </p>
 *
 * @author liyong
 * @since 2024-01-11
 */
@Service
@AllArgsConstructor
@Slf4j
public class JournalChangeDateServiceImpl implements JournalChangeDateService {
    private final JournalChangeDateMapper journalChangeDateMapper;
    private final StudentRecordClazzStartDateChangedService studentRecordClazzStartDateChangedService;
    private final JournalChangeDateLineService journalChangeDateLineService;
    private final BizNumberService bizNumberService;
    private final ClazzApi clazzApi;

    @Override
    public JournalChangeDateDTO getJournal(String id) {
        final JournalChangeDateDO journal = this.journalChangeDateMapper.selectJournal(id);
        JournalChangeDateDTO dto = new JournalChangeDateDTO();
        BeanUtils.copyProperties(journal, dto);
        return dto;
    }

    @Override
    public Page<JournalChangeDateDTO> search(JournalChangeDateSearch search) {
        JournalChangeDateQuery query = new JournalChangeDateQuery();
        BeanUtils.copyProperties(search, query);
        if (search.getStartDate() != null) {
            query.setStartDateTime(search.getStartDate().atStartOfDay());
        }
        if (search.getEndDate() != null) {
            query.setEndDateTime(search.getEndDate().atStartOfDay().plusDays(1));
        }
        var iPage = com.baomidou.mybatisplus.extension.plugins.pagination.Page.of(search.getPageNumber(), search.getPageSize());
        IPage<JournalChangeDateDO> page = journalChangeDateMapper.selectJournals(iPage, query);
        final List<JournalChangeDateDTO> items = page.getRecords().stream().map(r -> {
            JournalChangeDateDTO dto = new JournalChangeDateDTO();
            BeanUtils.copyProperties(r, dto);
            return dto;
        }).toList();
        return Page.of(
                (int) page.getCurrent(),
                (int) page.getSize(),
                (int) page.getTotal(),
                items);
    }

    @Override
    @Transactional
    public void dateChanged(JournalClazzStartDateChangedDTO changedDTO) {
        JournalChangeDate entity = JournalChangeDateConverter.convert(changedDTO);
        entity.setId(bizNumberService.next(BizNumberTypeEnum.CHANGE_DATE));
        final ClazzStudentResultDTO result = this.studentRecordClazzStartDateChangedService.findStudents(changedDTO.getClazzId(), changedDTO.getOldDate(), changedDTO.getNewDate());
        entity.setTotalCount(result.getTotal());
        final List<StudentRecordStudentDTO> students = result.getStudents();
        entity.setInvolveCount(students.size());
        this.journalChangeDateMapper.insert(entity);
        if (!students.isEmpty()) {
            final List<StudentRecordJournalInDateChangeDTO> studentChanges = this.saveJournalLines(entity, students);
            this.studentRecordClazzStartDateChangedService.updateStudentRecordInDates(studentChanges);
        }
    }

    private List<StudentRecordJournalInDateChangeDTO> saveJournalLines(JournalChangeDate journal,
                                                                       List<StudentRecordStudentDTO> students) {
        List<StudentRecordJournalInDateChangeDTO> result = new ArrayList<>();
        List<JournalChangeDateLineCreate> createCmds = students
                .stream()
                .map(s -> JournalChangeDateConverter.convert(s, journal))
                .toList();
        final Map<Integer, String> studentLineIdMap = this.journalChangeDateLineService.creatJournalChangeDateLines(createCmds);

        final ClazzDTO clazzDTO = this.clazzApi.queryByClassId(journal.getClazzId());
        students.forEach(s -> {
            StudentRecordJournalInDateChangeDTO dto = new StudentRecordJournalInDateChangeDTO();
            dto.setJournalId(journal.getId());
            final String lineId = studentLineIdMap.get(s.getStudentId());
            dto.setJournalLineId(lineId);
            dto.setStudentRecordId(s.getStudentRecordId());
            dto.setClazzId(journal.getClazzId());
            dto.setClassName(clazzDTO.getClassName());
            dto.setBeforeInDate(s.getInDate().toLocalDate());
            dto.setAfterInDate(journal.getAfterStartDate());
            result.add(dto);
        });
        return result;
    }
}
